package com.lanyuan.controller.api;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.lanyuan.controller.index.BaseController;
import com.lanyuan.entity.ActivityFormMap;
import com.lanyuan.entity.LuckydrawFormMap;
import com.lanyuan.entity.OrderinfoFormMap;
import com.lanyuan.entity.WinUserFormMap;
import com.lanyuan.mapper.ActivityMapper;
import com.lanyuan.mapper.LuckydrawMapper;
import com.lanyuan.mapper.OrderinfoMapper;
import com.lanyuan.mapper.WinUserMapper;
import com.lanyuan.thrid.wechat.utils.Api;
import com.lanyuan.thrid.wechat.utils.Constants;
import com.lanyuan.thrid.wechat.utils.SignatureUtil;
import com.lanyuan.thrid.wechat.utils.WechatManager;
import com.lanyuan.thrid.wechat.utils.XMLConverUtil;
import com.lanyuan.util.Common;
import com.lanyuan.util.TestUtil;
import com.lanyuan.vo.PrizeLevel;

/**
 * 
 * @author lanyuan 2014-11-19
 * @Email: mmm333zzz520@163.com
 * @version 3.0v
 */
@Controller
@RequestMapping("/api/wx/")
public class WxController extends BaseController {

	@Inject
	private OrderinfoMapper orderinfoMapper;

	@Inject
	private LuckydrawMapper luckydrawMapper;
	@Inject
	private ActivityMapper activityMapper;

	@Inject
	private WinUserMapper winuserMapper;

	/**
	 * 服务器接口验证
	 * 
	 * @param signature 微信加密签名
	 * @param timestamp 时间戳
	 * @param nonce 随机数
	 * @param echostr 随机字符串
	 */
	@RequestMapping(value = "dealwith", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
	public void dealwith(@RequestParam(required = true) String signature,
			@RequestParam(required = true) String timestamp, @RequestParam(required = true) String nonce,
			@RequestParam(required = true) String echostr, PrintWriter out) {
		// 重写totring方法，得到三个参数的拼接字符串
		List<String> list = new ArrayList<String>(3) {
			private static final long serialVersionUID = 2621444383666420433L;

			@Override
			public String toString() {
				return this.get(0) + this.get(1) + this.get(2);
			}
		};
		list.add(Constants.TOKEN);
		list.add(timestamp);
		list.add(nonce);
		Collections.sort(list);// 排序
		String tmpStr = DigestUtils.shaHex(list.toString());
		if (signature.equals(tmpStr)) {
			out.write(echostr);
		} else {
			out.write("check error!");
		}
		out.flush();
		out.close();
	}

	/**
	 * 处理微信服务器发过来的各种消息，包括：文本、图片、地理位置、音乐等等
	 * 
	 * @throws Exception
	 */
	@RequestMapping("dealwith")
	public void dealwith(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws Exception {
		Map<String, String> message = XMLConverUtil.convertToMap(request.getInputStream());
		// 只处理文本消息
		if ("text".equalsIgnoreCase(message.get("MsgType"))) {
			// 说明:1.一共3个参数，参数之间用空格或者制表符间隔
			// 2.中间等级必须为1-5
			// 固定消息格式wycj 中奖等级 手机号码 如:wycj 2 15872610238
			// 3.手机号码暂时只验证了11位数字
			Pattern p = Pattern.compile("^wycj\\s+([1-5])\\s+(\\d{11})$");
			String content = message.get("Content");
			Matcher m = p.matcher(content);
			while (m.find()) {
				// 处理作弊抽奖
				// 获取用户信息
				Map<String, String> userinfo = Api.userInfo(WechatManager.getAccess_token(),
						message.get("FromUserName"));
				// 获取当前开启的活动
				Map<String, Object> dataMap = new HashMap<String, Object>();
				dataMap = luckydrawMapper.findbyFrist("type", "1", LuckydrawFormMap.class);
				String pid = dataMap.get("id").toString();
				// 根据中奖等级获取中奖信息
				dataMap = activityMapper.findbyFrist("pid", pid, ActivityFormMap.class);

				WinUserFormMap winuserFormMap = new WinUserFormMap();
				winuserFormMap.put("pid", pid);
				winuserFormMap.put("openid", message.get("FromUserName"));
				winuserFormMap.put("nickname", userinfo.get("nickname"));
				winuserFormMap.put("imgpath", userinfo.get("headimgurl"));
				winuserFormMap.put("mobile", m.group(2));

				winuserFormMap.put("status", 1);// 0待验证1待兑奖2已兑奖
				winuserFormMap.put("zjdj", m.group(1));
				winuserFormMap.put("jpjs", PrizeLevel.getJpjs(Integer.parseInt(m.group(1))));
				winuserFormMap.put("authcode", TestUtil.jackpot());
				winuserFormMap.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
				winuserFormMap.put("jp", dataMap.get(PrizeLevel.getJp(Integer.parseInt(m.group(1)))));
				winuserMapper.addEntity(winuserFormMap);

			}

		}
	}

	/**
	 * 自动回复请求地址-添加抽奖用户信息
	 * 
	 * @throws Exception
	 */
	@RequestMapping("createUser")
	public String createUser(String code, HttpServletRequest request, HttpSession session) throws Exception {
		// 获取code，以获取openid
		Map<String, String> result = Api.oauth2AccessToken(code);
		if (StringUtils.isEmpty(result.get("openid"))) {
			return "redirect:" + Api.connectOauth2Authorize(Constants.CREATE_USER_URL, false);
		}

		String openid = result.get("openid");
		String subscribe = null;

		// 判断该微信号是否已关注
		Map<String, String> userinfo = Api.userInfo(WechatManager.getAccess_token(), openid);
		if (userinfo != null) {
			Map<String, Object> mapda = new HashMap<String, Object>();
			mapda.put("subscribe", userinfo.get("subscribe"));
			subscribe = mapda.get("subscribe").toString();
		}

		// 未关注
		if ("0".equals(subscribe)) {
			return "redirect:" + Constants.SUBSCRIBE_URL;
		}

		// 新增中奖用户
		// 获取当前开启的活动
		Map<String, Object> dataMap = new HashMap<String, Object>();
		dataMap = luckydrawMapper.findbyFrist("type", "1", LuckydrawFormMap.class);
		String pid = dataMap.get("id").toString();
		// 根据中奖等级获取中奖信息
		dataMap = activityMapper.findbyFrist("pid", pid, ActivityFormMap.class);

		WinUserFormMap winuserFormMap = new WinUserFormMap();
		winuserFormMap.put("pid", pid);
		winuserFormMap.put("openid", openid);
		winuserFormMap.put("nickname", userinfo.get("nickname"));
		winuserFormMap.put("imgpath", userinfo.get("headimgurl"));

		winuserFormMap.put("status", 3);// 0待验证1待兑奖2已兑奖
		winuserFormMap.put("authcode", TestUtil.jackpot());
		winuserFormMap.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
		winuserMapper.addEntity(winuserFormMap);

		return Common.BACKGROUND_PATH + "/wx/createUserSuccess";
	}

	/**
	 * 活动页面入口
	 * 
	 * @throws Exception
	 */
	@RequestMapping("activity")
	@Transactional(readOnly = false)
	public String activity(String code, HttpServletRequest request, Model model) throws Exception {
		// 如果当前不是授权回调地址则重定向
		// 生成网页授权地址（获取access_token过程中的跳转uri，通过跳转将code传入jsapi支付页面）
		// 获取当前开启的活动
		LuckydrawFormMap luckydrawFormMap = luckydrawMapper.findbyFrist("type", "1", LuckydrawFormMap.class);

		// 判断活动时间
		Calendar cNow = Calendar.getInstance();
		Calendar cBegin = Calendar.getInstance();
		Calendar cEnd = Calendar.getInstance();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		cBegin.setTime(luckydrawFormMap.getDate("startTime"));
		cEnd.setTime(luckydrawFormMap.getDate("endTime"));
		// 这里只是简单的做了范围判断，当前时间如果在开始前我也是作为活动结束处理的，想多写处理可以自己改下
		if (!(cNow.after(cBegin))) {
			Map<String, Object> luckydrawstart = new HashMap<String, Object>();
			luckydrawstart.put("ontice", "当前活动时间：" + "开始：" + df.format(luckydrawFormMap.getDate("startTime")) + "-"
					+ df.format(luckydrawFormMap.getDate("endTime")));
			luckydrawstart.put("msg", "活动未开始");
			model.addAttribute("winuser", luckydrawstart); // 当前中奖用户
			return Common.BACKGROUND_PATH + "/wx/noactivity";
		}
		if (!(cNow.before(cEnd))) {
			Map<String, Object> luckydrawstart = new HashMap<String, Object>();
			luckydrawstart.put("ontice", "当前活动时间：" + "开始：" + df.format(luckydrawFormMap.getDate("startTime")) + "-"
					+ df.format(luckydrawFormMap.getDate("endTime")));
			luckydrawstart.put("msg", "活动已结束，请下次再来");
			model.addAttribute("winuser", luckydrawstart); // 当前中奖用户
			return Common.BACKGROUND_PATH + "/wx/noactivity";
		}

		// 获取code，以获取openid
		Map<String, String> result = Api.oauth2AccessToken(code);
		if (StringUtils.isEmpty(result.get("openid"))) {
			return "redirect:" + Api.connectOauth2Authorize(Constants.ACTIVITY_URL, false);
		}

		String openid = result.get("openid");
		String subscribe = null;

		// 判断该微信号是否已关注
		Map<String, String> userinfo = Api.userInfo(WechatManager.getAccess_token(), openid);
		if (userinfo != null) {
			Map<String, Object> mapda = new HashMap<String, Object>();
			mapda.put("subscribe", userinfo.get("subscribe"));
			subscribe = mapda.get("subscribe").toString();
		}

		// 未关注
		if ("0".equals(subscribe)) {
			return "redirect:" + Constants.SUBSCRIBE_URL;
		}

		SortedMap<String, String> orderMap = new TreeMap<String, String>();
		orderMap.put("appid", Constants.APPID);// 公众账号ID
		orderMap.put("mch_id", Constants.MCHID);// 商户号
		orderMap.put("body", "支付抽奖活动");// 商品描述
		orderMap.put("out_trade_no", String.valueOf(System.currentTimeMillis()));// 商户订单号
		orderMap.put("total_fee", String.valueOf(Constants.PAY_MONEY));// 总金额,单位为分
		orderMap.put("spbill_create_ip", request.getRemoteAddr());// 终端ip
		orderMap.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));// 随机字符串
		orderMap.put("notify_url", Constants.NOTIFY_URL);// 通知地址
		orderMap.put("trade_type", "JSAPI");// 交易类型
		orderMap.put("openid", openid);// 用户标识
		// 使用统一接口获取prepay_id（即下订单）
		Map<String, String> orderResult = Api.payUnifiedorder(orderMap, Constants.KEY);

		// 生成jsapi支付参数
		SortedMap<String, String> jsApiParameters = new TreeMap<String, String>();
		jsApiParameters.put("appId", Constants.APPID);
		jsApiParameters.put("timeStamp", String.valueOf(System.currentTimeMillis()));
		jsApiParameters.put("nonceStr", UUID.randomUUID().toString().replaceAll("-", ""));
		jsApiParameters.put("signType", "MD5");
		jsApiParameters.put("package_", "prepay_id=" + orderResult.get("prepay_id"));
		jsApiParameters.put("paySign", SignatureUtil.generateSign(jsApiParameters, Constants.KEY));

		// 保存订单信息
		OrderinfoFormMap orderinfoAddMap = new OrderinfoFormMap();
		orderinfoAddMap.put("orderNo", orderMap.get("out_trade_no"));
		orderinfoAddMap.put("luckydrawId", String.valueOf(luckydrawFormMap.getLong("id")));
		orderinfoAddMap.put("openid", openid);
		orderinfoAddMap.put("state", 0);// 0:未支付 1:已支付 2:已抽奖
		orderinfoMapper.addEntity(orderinfoAddMap);
		WinUserFormMap winuserFormMap = getFormMap(WinUserFormMap.class);
		winuserFormMap = toFormMap(winuserFormMap, "1", "3", winuserFormMap.getStr("orderby"));
		winuserFormMap.put("column", "createTime");
		winuserFormMap.put("sort", "desc");
		List<WinUserFormMap> winuserdata = winuserMapper.findUserPage(winuserFormMap);// 不调用默认分页,调用自已的mapper中findUserPage
		model.addAttribute("jsApiParameters", jsApiParameters);// jsapi支付参数
		model.addAttribute("orderId", orderinfoAddMap.get("id"));// 订单信息
		model.addAttribute("activity", luckydrawFormMap); // 当前活动信息
		model.addAttribute("winuser", winuserdata); // 当前中奖用户

		return Common.BACKGROUND_PATH + "/wx/activity";
	}

	/**
	 * 接收微信支付通知
	 */
	@RequestMapping("notify_url")
	public void notify_url(HttpServletRequest request) {

	}

	/**
	 * 抽奖
	 * 
	 * @throws Exception
	 */
	@RequestMapping("licky")
	@Transactional(readOnly = false)
	public String licky(String orderId, HttpServletRequest request, Model model) throws Exception {
		try {
			// 验证该订单是否存在
			OrderinfoFormMap orderinfoFormMap = orderinfoMapper.findbyFrist("id", orderId, OrderinfoFormMap.class);
			// 该订单不存在或openid不存在或该订单是否已抽奖 都将直接跳转到活动页面重新下订单支付抽奖
			// if ((orderinfoFormMap == null) || StringUtils.isEmpty(orderinfoFormMap.getStr("openid"))
			// || (orderinfoFormMap.getInt("state") == 2)) {
			// return "redirect:" + Api.connectOauth2Authorize(Constants.ACTIVITY_URL, false);
			// }

			// 修改订单状态已支付
			OrderinfoFormMap orderinfoEditMap = new OrderinfoFormMap();
			orderinfoEditMap.put("id", orderId);
			orderinfoEditMap.put("state", 1);// 0:未支付 1:已支付 2:已抽奖
			orderinfoMapper.editEntity(orderinfoEditMap);
			// 开始抽奖
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String path = "/wx/result";
			String mensg = null;
			String jp = null;

			// 奖品信息
			Map<String, Object> activityFormMap = activityMapper.findbyFrist("pid",
					orderinfoFormMap.getInt("luckydrawId").toString(), ActivityFormMap.class);
			Integer result = TestUtil.lottery2(activityFormMap);
			if (result == 0) {
				path = "/wx/noresult";
				mensg = "未中奖";
			} else {
				mensg = PrizeLevel.getJpjs(result);
				jp = activityFormMap.get(PrizeLevel.getJp(result)).toString();
			}

			// 更新奖品信息
			activityMapper.editEntity(activityFormMap);
			// 修改订单状态
			orderinfoEditMap.put("state", 2); // // 0:未支付 1:已支付 2:已抽奖
			orderinfoMapper.editEntity(orderinfoEditMap);

			// 获取用户基本信息
			if (result > 0) {
				Map<String, String> userinfo = Api.userInfo(WechatManager.getAccess_token(),
						orderinfoFormMap.getStr("openid"));
				WinUserFormMap winuserFormMap = new WinUserFormMap();
				winuserFormMap.put("pid", orderinfoFormMap.getInt("luckydrawId").toString());
				winuserFormMap.put("openid", orderinfoFormMap.getStr("openid"));
				winuserFormMap.put("nickname", userinfo.get("nickname"));
				winuserFormMap.put("imgpath", userinfo.get("headimgurl"));

				winuserFormMap.put("status", 0);// 0待验证1待兑奖2已兑奖
				winuserFormMap.put("zjdj", result);
				winuserFormMap.put("jpjs", mensg);
				winuserFormMap.put("authcode", TestUtil.jackpot());
				winuserFormMap.put("createTime", df.format(new Date()));
				winuserFormMap.put("jp", jp);
				winuserMapper.addEntity(winuserFormMap);

				model.addAttribute("retult", winuserFormMap);
			}
			return Common.BACKGROUND_PATH + path;

		} catch (IOException e) {
			e.printStackTrace();
		}
		return "FAIL";
	}

}
